Skip to content

Conversation

@deepak0x
Copy link

@deepak0x deepak0x commented Jan 4, 2026

Proposed changes

This PR refactors the app to use @rocket.chat/rest-typings as the single source of truth for REST API type definitions.

Issue(s)

Closes #6232

How to test or reproduce

Screenshots

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • Improvement (non-breaking change which improves a current function)
  • New feature (non-breaking change which adds functionality)
  • Documentation update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works (if applicable)
  • I have added necessary documentation (if applicable)
  • Any dependent changes have been merged and published in downstream modules

Further comments

Summary by CodeRabbit

  • Refactor

    • Unified many REST v1 endpoint typings to derive from a central typings source, simplifying and standardizing API type definitions.
  • Bug Fixes

    • Safer API response handling and tighter guards/defaults to avoid undefined or malformed remote data across multiple flows.
  • New Features

    • Added a video-conference endpoint to update Jitsi timeout.
  • Chores

    • Added shared typing packages (@rocket.chat/core-typings, @rocket.chat/rest-typings v6.13.1).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 4, 2026

Walkthrough

Replaced many local REST typing definitions with re-exports from @rocket.chat/rest-typings / @rocket.chat/core-typings, removed local pagination types, adapted v1 endpoint typing files to derive signatures from those packages, added dependencies, and tightened several runtime type guards/casts.

Changes

Cohort / File(s) Summary
Helpers — removed local pagination types
app/definitions/rest/helpers/PaginatedRequest.ts, app/definitions/rest/helpers/PaginatedResult.ts
Deleted local PaginatedRequest and PaginatedResult type aliases; no local replacements re-exported.
Helpers index — typing refactor & re-exports
app/definitions/rest/helpers/index.ts
Rewrote to re-export utilities from @rocket.chat/rest-typings/@rocket.chat/core-typings; added Method/Path/PathPattern, GetParams/GetResult-style utilities, MethodToPath* maps, and ResultFor/ParamsFor types.
Bulk v1 endpoint typings migration
app/definitions/rest/v1/* (channels, chat, directory, emojiCustom, groups, im, omnichannel, settings, teams, videoConference, customUserStatus, permissions, push, roles, subscriptions, dm, invites, rooms, users, autotranslate, commands, e2e, moderation, etc.)
Replaced explicit in-file endpoint maps with adapter patterns importing Endpoints/specific endpoint types from @rocket.chat/rest-typings, stripping /v1/ prefixes via RemoveV1Prefix + Adapt*Endpoints, and re-exporting adapted maps. Some module-specific additions/removals/reshapes (see settings/roles/videoConference).
Selected v1 files with bespoke adjustments
app/definitions/rest/v1/settings.ts, app/definitions/rest/v1/roles.ts, app/definitions/rest/v1/videoConference.ts
settings.ts: reduced public surface, removed runtime type-guard exports, updated OauthCustomConfiguration and added isOauthCustomConfiguration; roles.ts: adjusted RoleCreate/RoleUpdate to local role interfaces and customized endpoint shapes; videoConference.ts: adapted endpoints and added 'video-conference/jitsi.update-timeout' POST.
Package manifest — new dependencies
package.json
Added @rocket.chat/[email protected] and @rocket.chat/[email protected].
REST service — loosened typing & payload casts
app/lib/services/restApi.ts
Many API calls/payloads cast to any; toggleReadStatus return loosened; request payload shapes frequently cast to accommodate typing differences.
Hook — stricter GET response handling
app/lib/hooks/useEndpointData.ts
GET handler now verifies response is an object with boolean success before resolving result or setting error.
Minor typing adjustments / defensive casts
assorted app/views/*, app/lib/methods/*, app/lib/hooks/*, app/ee/*
Numerous defensive casts to any/unknown, nullish coalescing, and tighter guards to avoid undefined access; mostly type-level changes without runtime logic alterations.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • diegolmello

Poem

🐇
I chewed old types beneath the moonlit rugs,
Pulled pagination roots and re-wrote plugs,
Mapped v1 paths to tidy, rested lines,
Now endpoints hop clean through typed designs. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and clearly describes the main refactoring objective: migrating to @rocket.chat/rest-typings as the single source of truth for REST API type definitions.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #6232 by replacing duplicated REST API type definitions with imports from @rocket.chat/rest-typings across 20+ endpoint files and helper modules.
Out of Scope Changes check ✅ Passed All code changes directly support the rest-typings migration. Minor defensive type casting and guard additions (e.g., undefined checks in views) align with supporting the new typing structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🧹 Recent nitpick comments
app/lib/methods/getSingleMessage.ts (2)

10-13: Double assertion as unknown as IMessage undermines type safety.

The _idid mapping correctly addresses the structural mismatch. However, the double cast (as unknown as T) is a TypeScript anti-pattern that completely bypasses the type system—if the API response shape changes or additional required fields are missing, the compiler won't catch it.

Since you're already spreading the message and adding id, consider either:

  1. Using a single assertion as IMessage (still not ideal but better), or
  2. Defining a proper return type from getSingleMessageService that TypeScript can verify against IMessage.
Minimal improvement using single assertion
 			return resolve({
 				...message,
 				id: message._id
-			} as unknown as IMessage);
+			} as IMessage);

15-15: Rejection without error information hinders debugging.

When result.success is false or message is undefined, rejecting without an error makes it difficult to diagnose failures upstream.

Suggested improvement
-			return reject();
+			return reject(new Error('Failed to fetch message or message not found'));
app/views/UserNotificationPreferencesView/index.tsx (1)

49-49: Double cast is safer but still indicates a type mismatch.

The as unknown as INotificationPreferences pattern is safer than direct as any since it makes the type assertion explicit. However, this indicates the API response type doesn't align with INotificationPreferences.

Consider updating INotificationPreferences to match the actual response shape from rest-typings, or importing the preferences type directly from @rocket.chat/rest-typings to eliminate this cast entirely — this would better align with the PR's goal of using rest-typings as the single source of truth.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4b46bc8 and de733a3.

📒 Files selected for processing (5)
  • app/lib/methods/getSingleMessage.ts
  • app/lib/services/restApi.ts
  • app/views/DiscussionsView/index.tsx
  • app/views/ReadReceiptView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/views/DiscussionsView/index.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
app/views/ReadReceiptView/index.tsx (1)
app/definitions/IMessage.ts (1)
  • IReadReceipts (189-196)
app/views/UserNotificationPreferencesView/index.tsx (2)
app/lib/services/restApi.ts (1)
  • getUserPreferences (359-361)
app/definitions/IUser.ts (1)
  • INotificationPreferences (108-115)
app/lib/methods/getSingleMessage.ts (1)
app/definitions/IMessage.ts (1)
  • IMessage (147-178)
🔇 Additional comments (20)
app/lib/services/restApi.ts (18)

260-260: LGTM — type cast for version-conditional params.

The as any cast accommodates the version-specific parameter shape differences between older and newer server versions. This is acceptable during the rest-typings migration.


276-276: LGTM — explicit undefined for optional parameter.

Using joinCode ?? undefined ensures the optional parameter is explicitly undefined rather than null, which aligns with the expected API contract.


337-346: LGTM — toggleReadStatus implementation.

The function correctly handles the read/unread toggle with appropriate endpoint selection and conditional payload construction for the readThreads flag.


359-361: LGTM — getUserPreferences now correctly omits userId.

Per past review feedback, the function signature was updated to call users.getPreferences without parameters, as the endpoint determines the user from auth headers.


429-429: LGTM — version-conditional endpoint with type cast.

The as any cast for the newer livechat/inquiries.returnAsInquiry endpoint is necessary since it may not be present in the current rest-typings version being used.


474-474: LGTM — endpoint cast for version-specific API.

The cast accommodates the livechat/config/routing endpoint that may not yet be typed in rest-typings.


490-490: LGTM — dynamic endpoint path requires cast.

The template literal endpoint with path parameters requires a cast since rest-typings may not support this pattern directly.


651-651: LGTM — type casts for profile update payload.

The as any casts bridge the gap between local IProfileParams and rest-typings definitions during migration.


659-659: LGTM — notifications payload cast.

The cast accommodates potential differences between local IRoomNotifications and rest-typings definitions.


702-702: LGTM — sort parameter cast.

The { uploadedAt: -1 } as any cast is needed because the sort object type may not match the expected rest-typings shape exactly.


808-808: LGTM — params cast for optional text parameter.

The cast accommodates the conditional text property in the params object.


818-818: LGTM — triggerId parameter typing.

The triggerId is correctly typed as string to align with the API expectations.


967-967: LGTM — endpoint and payload casts for e2e.resetRoomKey.

The as any casts are necessary since this endpoint may not be fully typed in rest-typings yet (as indicated by the // RC ? comment).


982-991: LGTM — chat.update payload casts.

The casts accommodate the different payload shapes (with content vs text) for the encrypted/unencrypted message update paths.


997-997: LGTM — narrowed push token type.

Using the union type 'apn' | 'gcm' is more precise than a generic string and correctly maps iOS to APNs and Android to GCM/FCM.


1083-1089: LGTM — guard for undefined user id added.

Per past review feedback, the function now properly guards against undefined id and returns a rejected promise with a clear error message before making the API call.


1098-1098: LGTM — endpoint and payload casts for rooms.invite.

The casts accommodate potential typing gaps for this endpoint in rest-typings.


601-601: The ignore.toString() conversion is correct and necessary.

Query parameters in GET requests are always strings, so converting the boolean ignore parameter to a string with .toString() is the proper way to format it for the API call. This ensures the server receives "true" or "false" as string values rather than JavaScript boolean primitives.

app/views/UserNotificationPreferencesView/index.tsx (2)

46-46: LGTM — getUserPreferences called without userId.

This correctly matches the updated getUserPreferences() function signature that no longer accepts a userId parameter.


57-57: LGTM — empty dependency array is correct.

Since getUserPreferences() no longer depends on userId, removing it from the dependency array is appropriate. The effect correctly runs once on mount.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@deepak0x deepak0x force-pushed the refactor/rest-typings-setup_and_helpers_migration branch from 39693ae to 1c1e6dc Compare January 4, 2026 07:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
scripts/verify-migration-phase.sh (1)

1-52: Consider adding test execution to match documentation.

MIGRATION_SUMMARY.md and MIGRATION_CHECKLIST.md both reference running yarn test as part of the verification process, but this script only checks TypeScript compilation and linting. Consider adding test execution or updating the documentation to reflect the actual verification steps.

🔎 Proposed addition of test execution
 echo "✅ Linting passed with 0 errors"
 
+# Run tests
+echo "🧪 Running tests..."
+if ! yarn test; then
+    echo "❌ Tests failed!"
+    exit 1
+fi
+echo "✅ Tests passed"
+
 echo ""
 echo "✅ Phase $PHASE verification complete!"
 echo "   - TypeScript: ✅"
 echo "   - Linting: ✅ (0 errors)"
+echo "   - Tests: ✅"
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3315fb4 and 39693ae.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (10)
  • .gitignore
  • MIGRATION_CHECKLIST.md
  • MIGRATION_PLAN.md
  • MIGRATION_SUMMARY.md
  • app/definitions/rest/COMPATIBILITY_LAYER.md
  • app/definitions/rest/helpers/PaginatedRequest.ts
  • app/definitions/rest/helpers/PaginatedResult.ts
  • app/definitions/rest/helpers/index.ts
  • package.json
  • scripts/verify-migration-phase.sh
🔇 Additional comments (8)
app/definitions/rest/COMPATIBILITY_LAYER.md (1)

1-52: Documentation looks good, but note the .gitignore conflict.

The compatibility layer documentation is well-structured and provides clear guidance with helpful examples. However, this file is listed in .gitignore (line 92), which conflicts with it being committed. Please refer to the review comment on .gitignore for resolution.

MIGRATION_PLAN.md (1)

1-315: Comprehensive migration plan, but conflicts with .gitignore.

The migration plan is well-structured with clear phases, time estimates, and quality gates. However, this file matches the *MIGRATION*.md pattern in .gitignore (line 88), which would prevent it from being tracked. Please refer to the review comment on .gitignore for resolution.

app/definitions/rest/helpers/PaginatedResult.ts (1)

1-2: No action needed—verification confirms the external type exists and all usages are type-safe.

The @rocket.chat/rest-typings package (v6.13.1) is properly declared in package.json, and the re-export is working correctly across all seven files that import PaginatedResult (directory.ts, settings.ts, teams.ts, videoConference.ts, omnichannel.ts, emojiCustom.ts, chat.ts). No type errors or import failures are present, confirming structure compatibility and type-safety.

package.json (1)

50-53: The specified versions (6.13.1) exist, are published, and have no known security vulnerabilities. They are compatible by design, released together as matched versions in Rocket.Chat 6.13.1. The exact version pinning indicates intentional selection for stable compatibility with a specific Rocket.Chat server release, which is appropriate for a mobile client targeting that version. No action needed.

app/definitions/rest/helpers/index.ts (1)

2-4: LGTM! Clear migration plan documented.

The TODO comments effectively communicate the migration strategy and rationale for maintaining the current implementation during the transition phase.

MIGRATION_SUMMARY.md (1)

1-58: Well-structured migration documentation.

The summary provides a clear overview of the migration process with helpful quick references, phase descriptions, quality gates, and important notes. The structure will guide developers effectively through the phased migration.

MIGRATION_CHECKLIST.md (1)

1-288: Excellent comprehensive migration checklist.

This checklist is well-structured and provides clear, actionable steps for each migration phase. The inclusion of verification commands (yarn lint, tsc --noEmit) after each category and standardized commit messages will help maintain quality and consistency throughout the migration process.

app/definitions/rest/helpers/PaginatedRequest.ts (1)

1-2: No action needed. The re-export to @rocket.chat/rest-typings is confirmed compatible.

The migration refactored the local PaginatedRequest definition to use the external package type, which correctly supports generic parameters T (request body) and an optional S (sort field) as evidenced by usage patterns throughout the codebase (PaginatedRequest<{ query: string }, 'name'>, PaginatedRequest<{ text: string }>). The external type includes the expected fields: count, offset, sort, and query. The codebase actively uses this re-export without type errors across multiple endpoint definitions.

@deepak0x deepak0x force-pushed the refactor/rest-typings-setup_and_helpers_migration branch 4 times, most recently from 861a4fa to d9b821b Compare January 4, 2026 08:04
Copy link
Member

@diegolmello diegolmello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!
Left a few comments.

@@ -1,4 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
// TODO: Once we migrate all endpoints to use @rocket.chat/rest-typings,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you do it on this PR or start the work on this PR, so it serves as a POC?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure...will try my best...

Preparation & Setup
- Install @rocket.chat/[email protected]
- Install @rocket.chat/[email protected] (required dependency)
- Explore and document package structure

Helper Types Migration
- Migrate PaginatedRequest to re-export from @rocket.chat/rest-typings
- Migrate PaginatedResult to re-export from @rocket.chat/rest-typings
- Update helpers/index.ts with TODO for future endpoint migration
- Keep custom ResultFor, Serialized, ErrorResult for SDK compatibility
- Remove PaginatedRequest.ts and PaginatedResult.ts wrapper files
- Use KeyOfEach and ReplacePlaceholders from @rocket.chat packages
- Implement rest-typings patterns: PathFor, PathWithParamsFor, PathWithoutParamsFor
- Add utilities: JoinPathPattern, UrlParams, MethodOf, ParamsFor
- Use MethodToPathPatternToParamsMap and MethodToPathPatternToResultMap patterns
- Fix TypeScript errors in useEndpointData with proper type guards
- Update import order in endpoint definition files
@deepak0x deepak0x force-pushed the refactor/rest-typings-setup_and_helpers_migration branch from 0aa5c81 to b5e17a7 Compare January 11, 2026 17:42
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
app/definitions/rest/helpers/index.ts (2)

1-1: Verify the necessity of the eslint-disable directive.

The no-unused-vars disable is common in type-only files, but it can mask legitimate issues. Consider reviewing whether all type parameters are actually necessary.


2-4: Track the migration TODO for future completion.

The POC comment indicates this is a temporary bridge implementation until full migration to @rocket.chat/rest-typings. This technical debt should be tracked to ensure the migration is completed.

Would you like me to create a tracking issue for the full migration to @rocket.chat/rest-typings endpoints (replacing the current Endpoints structure with /v1/ prefixed paths)?

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0aa5c81 and b5e17a7.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • app/definitions/rest/helpers/PaginatedRequest.ts
  • app/definitions/rest/helpers/PaginatedResult.ts
  • app/definitions/rest/helpers/index.ts
  • app/definitions/rest/v1/channels.ts
  • app/definitions/rest/v1/chat.ts
  • app/definitions/rest/v1/directory.ts
  • app/definitions/rest/v1/emojiCustom.ts
  • app/definitions/rest/v1/groups.ts
  • app/definitions/rest/v1/im.ts
  • app/definitions/rest/v1/omnichannel.ts
  • app/definitions/rest/v1/settings.ts
  • app/definitions/rest/v1/teams.ts
  • app/definitions/rest/v1/videoConference.ts
  • app/lib/hooks/useEndpointData.ts
  • package.json
💤 Files with no reviewable changes (2)
  • app/definitions/rest/helpers/PaginatedRequest.ts
  • app/definitions/rest/helpers/PaginatedResult.ts
✅ Files skipped from review due to trivial changes (1)
  • app/definitions/rest/v1/videoConference.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🧬 Code graph analysis (2)
app/definitions/rest/helpers/index.ts (1)
app/definitions/rest/v1/index.ts (1)
  • Endpoints (25-47)
app/lib/hooks/useEndpointData.ts (1)
app/definitions/rest/helpers/index.ts (4)
  • ErrorResult (182-182)
  • Serialized (48-56)
  • ResultFor (177-180)
  • MatchPathPattern (59-61)
🔇 Additional comments (13)
app/lib/hooks/useEndpointData.ts (1)

45-51: The error-handling logic is correct and intentional.

The SDK resolves promises in both success and error cases—it only rejects for network/connection errors. The logic correctly identifies errors when responses have success: false and treats all other resolved values as results. This matches the actual SDK behavior shown in the tests and is part of the @rocket.chat/rest-typings migration.

The guards are appropriate: e && typeof e === 'object' && 'success' in e && !e.success ensures non-objects and objects without a success property pass through to setResult, which is the correct behavior since the type system guarantees all SDK responses are objects with a success property.

Likely an incorrect or invalid review comment.

app/definitions/rest/v1/im.ts (1)

1-1: LGTM! Import migration correctly applied.

The migration from local PaginatedRequest to @rocket.chat/rest-typings follows the same pattern as other files in this PR. Type-only import is appropriate.

app/definitions/rest/v1/channels.ts (1)

1-1: LGTM! Consistent with the rest-typings migration.

The migration from local PaginatedRequest to @rocket.chat/rest-typings is correctly implemented.

app/definitions/rest/v1/teams.ts (1)

1-1: LGTM! Migration correctly applied.

The migration from local PaginatedResult to @rocket.chat/rest-typings is consistent with the broader refactoring effort.

app/definitions/rest/v1/settings.ts (1)

1-1: LGTM! Import migration correctly applied.

The migration from local PaginatedResult to @rocket.chat/rest-typings is correctly implemented. The type is used in an intersection type at line 70, which should work seamlessly with the external definition.

app/definitions/rest/v1/chat.ts (1)

1-1: LGTM! Migration to @rocket.chat/rest-typings is correctly implemented.

The type-only import from @rocket.chat/rest-typings for PaginatedResult is properly used and compatible. The old local definition has been removed, and the generic PaginatedResult<T> type matches the usage patterns in chat.ts and other REST endpoint definitions. Package version 6.13.1 is stable and was released as part of the official Rocket.Chat 6.13.1 release.

app/definitions/rest/v1/emojiCustom.ts (1)

1-1: LGTM! Clean migration to external types.

The import consolidation from local helpers to @rocket.chat/rest-typings aligns with the PR objectives and maintains existing type signatures.

app/definitions/rest/v1/directory.ts (1)

1-1: LGTM! Consistent with migration pattern.

The import source change maintains the existing type contract while aligning with the centralized type definitions from @rocket.chat/rest-typings.

app/definitions/rest/v1/omnichannel.ts (1)

1-1: LGTM! Extensive migration completed successfully.

The import migration to @rocket.chat/rest-typings is applied consistently across all OmnichannelEndpoints, maintaining type safety while reducing local type duplication.

app/definitions/rest/helpers/index.ts (3)

29-29: Type intersection ensures string compatibility.

The TPathPattern & string intersection correctly constrains the type for ReplacePlaceholders, ensuring that only string-compatible path patterns are processed.


175-180: LGTM! Error handling wrapper aligns with SDK needs.

The ResultFor type correctly wraps operation results with SuccessResult, FailureResult, and UnauthorizedResult patterns, providing comprehensive error handling for SDK consumers.


64-158: This is a POC adaptation—verify against actual rest-typings 6.13.1 when migrating endpoints.

The type utilities are correctly documented as adaptations rather than direct implementations from @rocket.chat/rest-typings. The file comment explicitly notes this is a temporary POC pattern awaiting full endpoint migration. The only direct import from rest-typings is ReplacePlaceholders, which is properly re-exported; the remaining utilities (UrlParams, MethodOf, PathFor, etc.) are locally implemented to match the current Endpoints structure.

Before merging, confirm:

  • The local type implementations are compatible with rest-typings 6.13.1's type signatures when endpoints are eventually migrated to use /v1/ prefix paths
  • No breaking changes in future rest-typings versions (6.13.1+) will affect the mapped type patterns used here

The TypeScript strict mode configuration and tsc in the lint script will catch type errors during compilation, but real compatibility should be verified once these types are actively used.

app/definitions/rest/v1/groups.ts (1)

1-1: Clean refactor with confirmed package compatibility.

The migration to @rocket.chat/rest-typings improves type consistency across the codebase. The package version 6.13.1 is correctly specified in package.json, and PaginatedRequest is properly exported and already in use across multiple endpoint definitions.

@deepak0x deepak0x requested a review from diegolmello January 12, 2026 18:22
- Migrate subscriptions, push, customUserStatus, directory, permissions, and roles endpoints
- Use type adapters to remove /v1/ prefix for compatibility with current path structure
- Fix type errors in DirectoryView and restApi.ts
- Update toggleReadStatus to use explicit endpoint types
- Fix push token type to use 'apn' | 'gcm' instead of string
- Add local extensions for roles.create, roles.update, and roles.getUsersInPublicRoles
@deepak0x deepak0x changed the title refactor: Install rest-typings and migrate helper types refactor: To use @rocket.chat/rest-typings as the single source of truth for REST API type definitions. Jan 15, 2026
…/rest-typings

- Migrate users, rooms, chat, channels, groups, im, dm, teams, emojiCustom, invites, and omnichannel endpoints
- Add type assertions where needed for compatibility with rest-typings types
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/lib/services/restApi.ts (1)

333-346: Fix inconsistent payload field naming in toggleReadStatus.

The function uses different field names for the room identifier between endpoints:

  • subscriptions.unread receives { roomId }
  • subscriptions.read receives { rid: roomId }

The subscriptions.read endpoint pattern is confirmed by app/lib/methods/readMessages.ts (line 37), which also uses { rid }. To maintain consistency, subscriptions.unread should use rid instead of roomId.

Additionally, the return type Promise<any> loses type safety. Consider defining the actual response type from rest-typings or adding a TODO comment to restore typing.

🤖 Fix all issues with AI agents
In `@app/lib/methods/getSingleMessage.ts`:
- Around line 8-9: getSingleMessage currently uses an unsafe type assertion "as
IMessage" hiding a structural mismatch (response has _id while IMessage expects
id); update getSingleMessage to either map the sdk.get('chat.getMessage') result
into the correct shape by copying _id to id before resolving (preserve all other
fields) or change the function return type to the raw response type from
rest-typings and remove the assertion so callers like getMessageInfo and
getThreadName explicitly handle the _id→id mapping; locate getSingleMessage and
the sdk.get('chat.getMessage') call to implement the mapping or adjust the
return type accordingly.

In `@app/lib/services/restApi.ts`:
- Around line 359-361: The getUserPreferences function is incorrectly passing a
userId to sdk.get for the 'users.getPreferences' endpoint which accepts no
parameters; update the function signature remove the userId argument, remove the
`{ userId } as any` payload, and call sdk.get('users.getPreferences') with no
second argument inside getUserPreferences; if you actually need another user's
preferences, replace the call with the correct endpoint/mechanism instead of
passing userId to 'users.getPreferences'.

In `@app/views/DiscussionsView/index.tsx`:
- Around line 67-73: The code casts result to any which removes type safety;
instead type the response returned by the API (avoid "as any") by
importing/using the appropriate type from `@rocket.chat/rest-typings` or declare a
local interface matching { messages?: IMessageFromServer[]; count?: number;
total?: number } and use a type guard/adapter to convert/validate result before
using it; then replace uses of || with nullish coalescing (use offset.current +=
resultData.count ?? 0 and total.current = resultData.total ?? 0) and keep the
existing logic around isSearching/setSearch/setDiscussions but operate on the
properly typed resultData.

In `@app/views/ReadReceiptView/index.tsx`:
- Line 90: The current cast "result.receipts as any" in ReadReceiptView
(index.tsx) bypasses TS safety; replace the cast by aligning the response type
from chat.getMessageReadReceipts with the expected receipts shape (or add a
proper adapter/mapper) and narrow the union with a type guard: inspect
result.success and then assign result.receipts to a strongly typed variable
(e.g., IReadReceipt[] or the appropriate interface from
`@rocket.chat/rest-typings`) or transform result.receipts into that interface;
update the rest-typings response type to include the receipts field if it’s
missing, or implement a local typed adapter function (e.g., mapReceiptsFromSdk)
and use that instead of casting to any.

In `@app/views/UserNotificationPreferencesView/index.tsx`:
- Line 49: The code is using an unsafe cast (result.preferences as any) which
bypasses typing; replace this by aligning types: import the preferences type
from `@rocket.chat/rest-typings` and use it for the local INotificationPreferences
(or update INotificationPreferences to match that imported type), change the
setPreferences call to accept the correctly typed value, and remove the other as
any in getUserPreferences in restApi.ts by updating that function to return the
proper typed response or add a small adapter function (e.g.,
transformUserPreferences) to convert the SDK shape into INotificationPreferences
before calling setPreferences.
♻️ Duplicate comments (2)
app/views/RoomView/RightButtons.tsx (1)

280-281: Duplicate as any cast pattern.

This is the same type-unsafe pattern as in Livechat.tsx. Once you extract a shared typed helper (as suggested in the other file), apply it here as well to maintain consistency and type safety across the codebase.

app/views/RoomActionsView/index.tsx (1)

411-412: Duplicate as any cast pattern.

Same type-unsafe workaround for department info. Consolidate with the shared helper suggested for Livechat.tsx.

🧹 Nitpick comments (18)
app/views/RoomInfoView/index.tsx (1)

171-172: Avoid as any casts; use proper type alignment instead.

These as any assertions undermine the type safety benefits of migrating to @rocket.chat/rest-typings. If there's a mismatch between the REST response type and local IUser, consider:

  1. Using a more specific type assertion (e.g., as Pick<IUser, 'username' | 'roles'>)
  2. Creating a type adapter function that maps the REST response to the expected local type
  3. Extending/aligning the local types with rest-typings

Note the inconsistency: the else branch (lines 178-179) handles roomUser without any casts, suggesting the types should be compatible.

♻️ Suggested approach
 				if (result.success) {
 					const { user } = result;
-					const r = handleRoles(user as any);
-					setRoomUser({ ...user, roles: r } as any);
+					const r = handleRoles(user as Pick<IUser, 'username' | 'roles'>);
+					setRoomUser({ ...user, roles: r } as IUser);
 				}

Or create a mapper function if the types diverge significantly:

const mapRestUserToRoomUser = (user: RestUserType): Partial<IUser> => ({
  _id: user._id,
  username: user.username,
  name: user.name,
  roles: user.roles,
  // ... map other fields
});
app/views/CannedResponsesListView/index.tsx (2)

88-88: Double cast indicates type mismatch between rest-typings and local definition.

The as unknown as ILivechatDepartment[] pattern is a valid escape hatch for the migration, but it signals that the @rocket.chat/rest-typings department type differs from the local ILivechatDepartment interface. Consider aligning the local interface with the external type definition in a follow-up to eliminate this cast.


130-130: Prefer double cast over as any for type safety.

Casting to any completely disables type checking on the state update. For consistency with line 88 and to retain some type safety, consider using the double cast pattern instead:

♻️ Suggested improvement
-				setCannedResponses(prevCanned => (debounced ? res.cannedResponses : [...prevCanned, ...res.cannedResponses]) as any);
+				setCannedResponses(prevCanned =>
+					(debounced ? res.cannedResponses : [...prevCanned, ...res.cannedResponses]) as unknown as ICannedResponse[]
+				);

This maintains the type escape hatch needed for the migration while preserving the declared state type.

app/lib/methods/getCustomEmojis.ts (1)

140-142: Unsafe type assertion masks a type mismatch.

The as unknown as TCustomEmojiModel[] cast bypasses type safety entirely. The API returns raw emoji objects (with _id), while TCustomEmojiModel is a WatermelonDB Model type (with id and Model methods). This mismatch is evident in updateEmojis where update items are accessed via ._id but allRecords items via .id.

Consider updating the IUpdateEmojis interface to use the correct API response type (e.g., from @rocket.chat/rest-typings) for update and remove instead of TCustomEmojiModel[]:

♻️ Suggested approach
+import type { ICustomEmoji } from '@rocket.chat/core-typings'; // or appropriate type from rest-typings

 interface IUpdateEmojis {
-	update: TCustomEmojiModel[];
-	remove?: TCustomEmojiModel[];
+	update: ICustomEmoji[];
+	remove?: ICustomEmoji[];
 	allRecords: TCustomEmojiModel[];
 }

Then the call site would not need the unsafe cast:

-const changedEmojis = await updateEmojis({ update: (update || []) as unknown as TCustomEmojiModel[], remove: (remove || []) as unknown as TCustomEmojiModel[], allRecords });
+const changedEmojis = await updateEmojis({ update: update || [], remove: remove || [], allRecords });
app/views/ThreadMessagesView/index.tsx (2)

345-351: Prefer proper type adapters over as any casts.

The as any casts bypass TypeScript's type safety entirely, which undermines the goal of using @rocket.chat/rest-typings as the source of truth. If the types from the external package don't match the internal IMessage type expected by updateThreads, consider:

  1. Creating a type adapter function to map the external thread type to IMessage
  2. Using a more specific type assertion if the types are compatible
  3. Updating updateThreads to accept the external type directly

The fallback resultData.count || result.threads.length suggests the response shape is uncertain—if count exists on the actual API response but not in the types, consider extending the type definition or using a type guard.

Example type adapter approach
// Define adapter if types differ structurally
type ThreadsListResponse = Awaited<ReturnType<typeof getThreadsList>>;

const mapThreadsToMessages = (threads: ThreadsListResponse['threads']): IMessage[] => {
  return threads.map(thread => buildMessage(thread) as IMessage);
};

// Then use:
this.updateThreads({ update: mapThreadsToMessages(result.threads), lastThreadSync });

For the count property, if it's a known part of the API response:

// Use type assertion with a specific interface
interface ThreadsListResultWithCount {
  count?: number;
  threads: { length: number };
}
const resultData = result as ThreadsListResultWithCount;

370-370: Same as any pattern as in load—apply consistent type handling.

This cast has the same type safety concerns noted above. When refactoring the load method, apply the same adapter pattern here for consistency.

app/ee/omnichannel/lib/subscriptions/inquiry.ts (1)

93-94: Consider fixing the type at the source instead of inline annotations.

The inline type annotations on lines 93–94 suggest that departments is loosely typed after the SDK call. The root cause is the as any cast on the sdk.get() URL in getAgentDepartments, which prevents TypeScript from inferring the response shape. While the annotations work, they:

  1. Add verbosity that wouldn't be needed if getAgentDepartments explicitly returned a typed response
  2. Could mask type mismatches if the actual API response differs from the assumed { departmentId: string } shape

Instead of adding inline type guards, either remove the as any cast from the SDK call or add an explicit return type to getAgentDepartments using the existing OmnichannelEndpoints type from @rocket.chat/rest-typings. This would allow TypeScript to automatically infer the correct types downstream.

app/views/ForwardLivechatView.tsx (1)

79-88: Double cast bypasses type safety and masks API response structure mismatch.

The as unknown as IServerRoom pattern silences the compiler but doesn't guarantee that the actual rooms.info API response includes all properties required by IServerRoom (e.g., u, uids, usersCount). If the API returns a partial room object, property accesses could fail at runtime.

The root issue is that sdk.get('rooms.info', { roomId }) has no explicit return type. Consider:

  1. Type the getRoomInfo call using the response type from @rocket.chat/rest-typings
  2. Create a mapper function that extracts and validates only the properties actually needed (servedBy, departmentId)
  3. Replace the local IServerRoom with the canonical type from the external package
app/views/MessagesView/index.tsx (1)

190-190: Double as any cast masks type incompatibility between rest-typings and IServerAttachment[].

The input and output casts to any suppress TypeScript checking for this entire expression. Since sdk.get() is strongly typed via rest-typings generics, result.files has a defined type that doesn't match what Encryption.decryptFiles expects. Rather than silencing the compiler:

  1. Check the actual type that rest-typings defines for the files endpoint response
  2. Update IServerAttachment[] to match, or add a type adapter if rest-typings has a different file structure
  3. Ensure decryptFiles properly types its return value instead of falling back to any
app/views/RoomInfoView/Livechat.tsx (1)

35-36: Avoid as any cast; extract a typed helper instead.

Casting result as any defeats the purpose of adopting typed REST definitions. This same pattern appears in at least three files (Livechat.tsx, RightButtons.tsx, RoomActionsView/index.tsx), which suggests creating a shared utility.

Consider narrowing the type or adding a type guard:

♻️ Suggested approach

Create a helper in the REST API layer that properly types the department response:

// In app/lib/services/restApi.ts or a dedicated helper
export const getDepartmentFromResult = (
  result: Awaited<ReturnType<typeof getDepartmentInfo>>
): ILivechatDepartment | undefined => {
  if (result.success && 'department' in result) {
    return result.department as ILivechatDepartment;
  }
  return undefined;
};

Then usage becomes type-safe:

-const resultData = result as any;
-setDepartment(resultData.department as ILivechatDepartment);
+const dept = getDepartmentFromResult(result);
+if (dept) setDepartment(dept);
app/definitions/rest/v1/invites.ts (1)

1-9: Consider extracting RemoveV1Prefix to a shared utility.

The RemoveV1Prefix type is duplicated across multiple endpoint definition files (channels.ts, chat.ts, dm.ts, groups.ts, im.ts, omnichannel.ts, rooms.ts, invites.ts, etc.). Extract it to a common location to reduce duplication.

♻️ Suggested refactor

Create a shared utility file:

// app/definitions/rest/v1/helpers.ts
export type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

export type AdaptEndpoints<T> = {
  [K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

Then each endpoint file becomes simpler:

-import type { InvitesEndpoints as RestTypingsInvitesEndpoints } from '@rocket.chat/rest-typings';
-
-type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;
-
-type AdaptInvitesEndpoints<T> = {
-	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-};
-
-export type InvitesEndpoints = AdaptInvitesEndpoints<RestTypingsInvitesEndpoints>;
+import type { InvitesEndpoints as RestTypingsInvitesEndpoints } from '@rocket.chat/rest-typings';
+import type { AdaptEndpoints } from './helpers';
+
+export type InvitesEndpoints = AdaptEndpoints<RestTypingsInvitesEndpoints>;
app/definitions/rest/v1/channels.ts (1)

1-9: Transformation approach is correct; consider extracting shared utility types.

The type transformation correctly strips the /v1/ prefix from endpoint keys. However, RemoveV1Prefix<T> and the Adapt*Endpoints<T> pattern are duplicated across multiple files (channels, chat, users, dm, im, etc.).

Consider extracting these to a shared utility file to reduce duplication:

♻️ Suggested shared utility

Create a shared utility file (e.g., app/definitions/rest/v1/helpers.ts):

export type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

export type AdaptEndpoints<T> = {
  [K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

Then simplify each endpoint file:

-import type { ChannelsEndpoints as RestTypingsChannelsEndpoints } from '@rocket.chat/rest-typings';
-
-type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;
-
-type AdaptChannelsEndpoints<T> = {
-	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-};
-
-export type ChannelsEndpoints = AdaptChannelsEndpoints<RestTypingsChannelsEndpoints>;
+import type { ChannelsEndpoints as RestTypingsChannelsEndpoints } from '@rocket.chat/rest-typings';
+import type { AdaptEndpoints } from './helpers';
+
+export type ChannelsEndpoints = AdaptEndpoints<RestTypingsChannelsEndpoints>;
app/definitions/rest/v1/rooms.ts (1)

1-9: Consider extracting RemoveV1Prefix to a shared utility.

The implementation is correct and the approach of deriving endpoint types from @rocket.chat/rest-typings is sound. However, RemoveV1Prefix<T> is duplicated across multiple files (rooms.ts, teams.ts, emojiCustom.ts, omnichannel.ts, and likely others such as channels.ts, chat.ts, groups.ts per the AI summary).

Extract this helper to a shared location to reduce duplication and simplify future maintenance.

Example shared utility file

Create a file like app/definitions/rest/v1/helpers.ts:

export type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

export type AdaptEndpoints<T> = {
	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

Then in each endpoint file:

-type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;
-
-type AdaptRoomsEndpoints<T> = {
-	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-};
-
-export type RoomsEndpoints = AdaptRoomsEndpoints<RestTypingsRoomsEndpoints>;
+import type { AdaptEndpoints } from './helpers';
+
+export type RoomsEndpoints = AdaptEndpoints<RestTypingsRoomsEndpoints>;
app/lib/services/restApi.ts (4)

260-260: Consider documenting why as any is needed here.

The conditional param structure (different shapes for channels vs groups, and version-dependent fields) likely doesn't align with the strict rest-typings definitions. This cast is acceptable for now, but consider adding a brief comment explaining the type mismatch or filing a follow-up to properly type this once rest-typings supports the variant shapes.


425-434: Document that this endpoint may not be in rest-typings yet.

The livechat/inquiries.returnAsInquiry endpoint (RC 7.12.0+) requires as any casts, likely because it's not yet defined in the installed @rocket.chat/rest-typings version. Consider adding a comment or TODO to remove the casts when rest-typings is updated.


488-490: Consider separating query params from the URL path.

The query parameter enabledDepartmentsOnly=true is embedded in the URL string. For consistency with other SDK calls and better type support in the future, consider passing it as a params object if the SDK supports it:

sdk.get(`livechat/agents/${uid}/departments`, { enabledDepartmentsOnly: true })

965-968: Clarify the endpoint version and return type.

The // RC ? comment indicates uncertainty about when this endpoint was introduced. The return type Promise<boolean | {}> is also unusual. Consider:

  1. Documenting the actual RC version if known
  2. Refining the return type to match the actual API response
app/lib/methods/getSingleMessage.ts (1)

4-15: Consider refactoring to avoid the Promise constructor anti-pattern.

Wrapping async inside new Promise() is redundant and can obscure errors. This is pre-existing code, but a future cleanup could simplify it:

♻️ Suggested refactor
-const getSingleMessage = (messageId: string): Promise<IMessage> =>
-	new Promise(async (resolve, reject) => {
-		try {
-			const result = await getSingleMessageService(messageId);
-			if (result.success && result.message) {
-				return resolve(result.message as IMessage);
-			}
-			return reject();
-		} catch (e) {
-			return reject(e);
-		}
-	});
+const getSingleMessage = async (messageId: string): Promise<IMessage> => {
+	const result = await getSingleMessageService(messageId);
+	if (result.success && result.message) {
+		return result.message as IMessage;
+	}
+	throw new Error('Failed to fetch message');
+};
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99c9f7b and ebd798d.

📒 Files selected for processing (31)
  • app/definitions/rest/v1/channels.ts
  • app/definitions/rest/v1/chat.ts
  • app/definitions/rest/v1/dm.ts
  • app/definitions/rest/v1/emojiCustom.ts
  • app/definitions/rest/v1/groups.ts
  • app/definitions/rest/v1/im.ts
  • app/definitions/rest/v1/invites.ts
  • app/definitions/rest/v1/omnichannel.ts
  • app/definitions/rest/v1/rooms.ts
  • app/definitions/rest/v1/teams.ts
  • app/definitions/rest/v1/users.ts
  • app/ee/omnichannel/lib/subscriptions/inquiry.ts
  • app/lib/hooks/useUserData.ts
  • app/lib/methods/getCustomEmojis.ts
  • app/lib/methods/getRoomInfo.ts
  • app/lib/methods/getSingleMessage.ts
  • app/lib/services/restApi.ts
  • app/views/CannedResponsesListView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/ForwardLivechatView.tsx
  • app/views/LivechatEditView.tsx
  • app/views/MessagesView/index.tsx
  • app/views/ReadReceiptView/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomInfoView/Livechat.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/definitions/rest/v1/groups.ts
🧰 Additional context used
🧬 Code graph analysis (10)
app/lib/methods/getSingleMessage.ts (1)
app/definitions/IMessage.ts (1)
  • IMessage (147-178)
app/views/ForwardLivechatView.tsx (1)
app/definitions/IRoom.ts (1)
  • IServerRoom (152-242)
app/views/RoomInfoView/Livechat.tsx (1)
app/definitions/ILivechatDepartment.ts (1)
  • ILivechatDepartment (1-23)
app/views/SearchMessagesView/index.tsx (1)
app/definitions/IMessage.ts (2)
  • IMessageFromServer (109-137)
  • TMessageModel (180-183)
app/views/CannedResponsesListView/index.tsx (1)
app/definitions/ILivechatDepartment.ts (1)
  • ILivechatDepartment (1-23)
app/lib/services/restApi.ts (1)
app/lib/notifications/index.ts (1)
  • getDeviceToken (83-83)
app/views/RoomActionsView/index.tsx (1)
app/definitions/ILivechatDepartment.ts (1)
  • ILivechatDepartment (1-23)
app/lib/methods/getRoomInfo.ts (1)
app/definitions/IRoom.ts (1)
  • RoomType (147-147)
app/views/RoomView/RightButtons.tsx (1)
app/definitions/ILivechatDepartment.ts (1)
  • ILivechatDepartment (1-23)
app/lib/methods/getCustomEmojis.ts (1)
app/definitions/IEmoji.ts (1)
  • TCustomEmojiModel (35-35)
🔇 Additional comments (29)
app/lib/methods/getRoomInfo.ts (2)

25-25: LGTM! Good defensive null check.

Adding the explicit result.room guard is a sensible improvement that prevents potential runtime errors if the API response lacks the room property despite success: true.


30-30: Type cast is consistent with existing pattern.

The as RoomType assertion aligns with line 20 and is a reasonable adaptation for the rest-typings migration where the external package may define a broader type for the t property.

app/views/SearchMessagesView/index.tsx (1)

182-182: LGTM!

The || [] fallback correctly handles the case where result.messages is undefined (from the optional chaining on line 164). The type assertion to (IMessageFromServer | TMessageModel)[] is appropriate here since the method needs to return a union type that accommodates both server responses and local WatermelonDB models returned from the encrypted room branch.

app/views/TeamChannelsView.tsx (1)

336-363: Good defensive check, but verify the empty params fallback behavior.

The added check for result.room is a sound improvement that prevents accessing properties on a potentially undefined object. However, when the condition fails (either !result.success or !result.room), goRoom is still invoked with an empty params object, which could lead to unexpected navigation behavior or errors downstream.

Consider whether an early return or user feedback should be provided when room info cannot be retrieved:

Suggested improvement
 onPressItem = debounce(
     async (item: IItem) => {
         logEvent(events.TC_GO_ROOM);
         const { isMasterDetail } = this.props;
         try {
-            let params = {};
             const result = await getRoomInfo(item._id);
-            if (result.success && result.room) {
-                params = {
-                    rid: item._id,
-                    name: getRoomTitle(result.room),
-                    joinCodeRequired: result.room.joinCodeRequired,
-                    t: result.room.t,
-                    teamId: result.room.teamId
-                };
+            if (!result.success || !result.room) {
+                showErrorAlert(I18n.t('Room_not_found'));
+                return;
             }
+            const params = {
+                rid: item._id,
+                name: getRoomTitle(result.room),
+                joinCodeRequired: result.room.joinCodeRequired,
+                t: result.room.t,
+                teamId: result.room.teamId
+            };
             goRoom({ item: params, isMasterDetail });
         } catch (e: any) {
app/lib/methods/getCustomEmojis.ts (1)

127-130: LGTM on parameter shape change.

The updated parameter shape { query: string; updatedSince?: string } aligns with the emoji-custom.list endpoint definition from @rocket.chat/rest-typings. Initializing with { query: '' } correctly satisfies the required parameter.

app/views/LivechatEditView.tsx (1)

124-124: The endpoint's type annotation should be improved before enforcing strict types on the callback.

The use of any on line 124 is a consequence of the endpoint being cast to as any in app/lib/services/restApi.ts:490. While using a proper type from @rocket.chat/rest-typings would be ideal, the SDK cannot infer correct types when the endpoint path itself is marked as any. Consider fixing the root cause by removing or refining the as any cast on the endpoint definition first, which would then allow the callback parameter to receive proper typing through the SDK's generic ResultFor<'GET', MatchPathPattern<TPath>> mechanism.

app/lib/hooks/useUserData.ts (1)

35-36: LGTM!

Good defensive defaults. The fallbacks ensure consistency with the initial state shape and prevent potential undefined propagation to child components.

app/views/RoomActionsView/index.tsx (3)

203-208: LGTM!

Good use of nullish coalescing to handle potentially undefined counters.members. The distinction between ?? undefined (for state) and ?? 0 (for the update function) correctly preserves the semantic difference between "unknown count" and "zero members".


246-247: Consistent nullish coalescing.

Same defensive pattern applied correctly in the componentDidMount path.


612-612: Remove the unnecessary any cast if isLastOwner is available from the response type, or extend the type locally if it's missing.

The (r as any).isLastOwner cast suggests isLastOwner is not typed in the teamListRoomsOfUser response from the SDK (which uses @rocket.chat/rest-typings). However, isLastOwner is already defined in the local IRoom interface as an optional boolean. Compare this with RoomMembersView/helpers.ts:156, which handles the same API response by casting the entire loop variable to any instead of just the property. If the endpoint's type definition in rest-typings lacks isLastOwner, consider either extending the response type locally or opening an issue upstream to add it to the type definitions.

app/definitions/rest/v1/chat.ts (1)

1-9: LGTM!

The transformation logic is correct and follows the same pattern established in other endpoint files. The duplication concern applies here as well—once the shared utility is extracted, this file can be simplified.

app/definitions/rest/v1/users.ts (1)

1-9: LGTM!

Consistent with the transformation pattern used across other endpoint definition files. The type mapping correctly adapts RestTypingsUsersEndpoints by stripping the /v1/ prefix.

app/definitions/rest/v1/dm.ts (1)

1-9: LGTM!

Follows the established pattern for adapting REST typings. The transformation correctly maps RestTypingsDmEndpoints to DmEndpoints with prefix stripping.

app/definitions/rest/v1/im.ts (1)

1-9: LGTM!

Consistent with the transformation approach across all endpoint definition files. The migration to @rocket.chat/rest-typings as the single source of truth is well-structured.

app/definitions/rest/v1/rooms.ts (1)

11-13: LGTM!

TRoomsMediaResponse is unchanged and remains correctly defined as a local type.

app/definitions/rest/v1/teams.ts (1)

1-9: LGTM — same refactor opportunity as noted in rooms.ts.

The adapter pattern is correctly implemented. The RemoveV1Prefix and AdaptTeamsEndpoints helpers duplicate the same logic from other files and would benefit from consolidation into a shared utility.

app/definitions/rest/v1/emojiCustom.ts (1)

1-9: LGTM — same refactor opportunity applies.

Correctly derives EmojiCustomEndpoints from the external rest-typings package. The duplicated helper types should be consolidated per the suggestion in rooms.ts.

app/definitions/rest/v1/omnichannel.ts (1)

1-9: LGTM — same refactor opportunity applies.

Correctly derives OmnichannelEndpoints from the external rest-typings package. Consider consolidating the duplicated helper types as suggested in the rooms.ts review.

app/lib/services/restApi.ts (11)

271-277: LGTM!

Converting null to undefined via ?? undefined aligns with rest-typings expectations for optional parameters.


473-478: LGTM for the routing config endpoint cast.

The livechat/config/routing endpoint (RC 7.11.0+) cast is acceptable since it's likely not yet in rest-typings.


599-601: LGTM!

Converting the boolean ignore to string via .toString() aligns with the API's expected parameter type.


646-651: LGTM with reservation.

The as any casts on data and customFields bypass rest-typings validation. The local types appear reasonable, but consider verifying alignment with rest-typings definitions when refining this migration.


657-659: LGTM!


696-704: LGTM!

The sort object cast is acceptable - MongoDB-style sort objects often need casting due to strict typing constraints.


797-809: LGTM!


970-991: LGTM!

The dual payload structure (content vs text) for encrypted and regular messages requires casting since rest-typings likely doesn't model both variants.


993-1011: LGTM!

Explicit type annotation 'apn' | 'gcm' ensures the literal union type is preserved for rest-typings compatibility.


1083-1086: LGTM!


1095-1095: LGTM!

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Fix CommandsEndpoints and AutoTranslateEndpoints imports by extracting from Endpoints interface
- Fix LoginServiceConfiguration import to use @rocket.chat/core-typings
- Fix runSlashCommand to make triggerId required to match endpoint definition
- Fix getSlashCommands type assertions for commands.list endpoint
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/definitions/rest/v1/videoConference.ts (1)

9-13: Fix return type: endpoint returns Promise<void>, not void.

The POST method for this endpoint is typed incorrectly. The actual usage in app/lib/methods/videoConfTimer.ts calls .catch() on the result of updateJitsiTimeout, which requires the return type to be a Promise:

updateJitsiTimeout(rid).catch((e: unknown) => console.log(e));

The return type should be Promise<void> to match the actual behavior of sdk.post():

'video-conference/jitsi.update-timeout': {
	POST: (params: { roomId: string }) => Promise<void>;
};
🤖 Fix all issues with AI agents
In `@app/definitions/rest/v1/channels.ts`:
- Around line 5-7: The closing brace in the type declaration for
AdaptChannelsEndpoints has inconsistent indentation (an extra tab before the
brace); align the closing brace with the start of the type declaration so it
matches the indentation of "type AdaptChannelsEndpoints<T> = {" and the opening
brace—edit the line containing the trailing brace for AdaptChannelsEndpoints to
remove the extra tab so formatting is consistent with RemoveV1Prefix and the
rest of the file.

In `@app/definitions/rest/v1/customUserStatus.ts`:
- Around line 11-13: The closing brace in the type declaration
AdaptCustomUserStatusEndpoints has extra indentation; adjust the closing brace
for that mapped type to match the opening indentation (remove the double tab so
the brace aligns with the type declaration), ensuring consistent indentation for
the entire type block.

In `@app/definitions/rest/v1/settings.ts`:
- Line 67: The isOauthCustomConfiguration type guard currently always returns
Boolean(config), which accepts any truthy value and doesn't validate required
fields; update isOauthCustomConfiguration to perform real runtime checks for the
OauthCustomConfiguration shape (e.g., verify presence and types of required
properties like clientId, clientSecret, redirectUri, or whichever fields the
OauthCustomConfiguration interface declares) or delete the function entirely if
runtime validation is unnecessary and you rely solely on compile-time types;
reference the isOauthCustomConfiguration function and the
OauthCustomConfiguration type when making the change.
- Around line 69-80: The local declaration of SettingsEndpoints redefines the
transformed endpoint 'settings/:_id' (from
AdaptSettingsEndpoints<RestTypingsSettingsEndpoints>) which can produce a union
if the local GET/POST signatures differ from the upstream; either add a concise
in-line comment above the 'settings/:_id' block stating that this is an
intentional override of the upstream type (mentioning AdaptSettingsEndpoints and
RestTypingsSettingsEndpoints) and why, or confirm and align the local signatures
(GET returning Pick<ISetting,'_id'|'value'> and POST accepting
SettingsUpdateProps) so they exactly match the upstream contract to avoid a
merged union type. Ensure the comment references the symbols SettingsEndpoints,
'settings/:_id', ISetting, and SettingsUpdateProps so future readers know the
override is deliberate and compatible.

In `@app/definitions/rest/v1/teams.ts`:
- Around line 5-7: The closing brace in the generic type declaration for
AdaptTeamsEndpoints has inconsistent indentation (an extra tab); fix the
formatting by aligning the closing brace with the opening "type
AdaptTeamsEndpoints<T> = {" line and the rest of the block so it matches the
style used in channels.ts—adjust the indentation of the line containing "};"
that closes the mapped type using RemoveV1Prefix and the mapped key signature.
♻️ Duplicate comments (1)
app/lib/services/restApi.ts (1)

359-361: The users.getPreferences endpoint does not accept a userId parameter.

This issue was previously identified. The API returns preferences for the authenticated user based on headers only—the userId parameter will be ignored. The as any cast masks an incorrect API call.

🧹 Nitpick comments (4)
app/lib/services/restApi.ts (2)

337-346: Return type loosened to Promise<any> reduces caller type safety.

Changing from a typed response to Promise<any> means callers lose compile-time guarantees on the response shape. If the rest-typings package provides proper response types for subscriptions.read and subscriptions.unread, consider using them instead of any.


965-968: Track as any casts for post-migration cleanup.

This file has accumulated many as any casts (e2e.resetRoomKey, chat.update, users.removeOtherTokens, rooms.invite, etc.) as workarounds during the rest-typings migration. Consider:

  1. Opening an issue to track these for cleanup
  2. Adding inline TODOs with issue references
  3. Contributing missing type definitions upstream to @rocket.chat/rest-typings
app/definitions/rest/v1/channels.ts (1)

1-9: Consider centralizing RemoveV1Prefix<T> into a shared utility type.

This helper type is duplicated across multiple endpoint definition files (channels.ts, moderation.ts, commands.ts, teams.ts, customUserStatus.ts, and likely others). Extract it to a shared location (e.g., app/definitions/rest/v1/helpers.ts) and import where needed.

♻️ Suggested shared helper

Create a new file app/definitions/rest/v1/helpers.ts:

export type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

export type AdaptEndpoints<T> = {
	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

Then in each endpoint file:

-type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;
-
-type AdaptChannelsEndpoints<T> = {
-	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-	};
+import type { AdaptEndpoints } from './helpers';

-export type ChannelsEndpoints = AdaptChannelsEndpoints<RestTypingsChannelsEndpoints>;
+export type ChannelsEndpoints = AdaptEndpoints<RestTypingsChannelsEndpoints>;
app/definitions/rest/v1/e2e.ts (1)

3-7: Extract RemoveV1Prefix to a shared utilities file to reduce duplication across 23 endpoint modules.

RemoveV1Prefix and the adapter type pattern are identically duplicated across all v1 endpoint files (channels, chat, e2e, rooms, users, etc.). Define these once in app/definitions/rest/helpers.ts and import as needed.

♻️ Suggested refactoring

Create shared helper file:

// app/definitions/rest/helpers.ts
export type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;

export type AdaptEndpoints<T> = {
  [K in keyof T as RemoveV1Prefix<K & string>]: T[K];
};

Then in each endpoint file:

 import type { E2eEndpoints as RestTypingsE2eEndpoints } from '@rocket.chat/rest-typings';
+import type { AdaptEndpoints } from '../helpers';

-type RemoveV1Prefix<T> = T extends `/v1/${infer Rest}` ? Rest : T;
-
-type AdaptE2eEndpoints<T> = {
-	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-};
-
-export type E2eEndpoints = AdaptE2eEndpoints<RestTypingsE2eEndpoints> & {
+export type E2eEndpoints = AdaptEndpoints<RestTypingsE2eEndpoints> & {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ebd798d and 853bf4e.

📒 Files selected for processing (12)
  • app/definitions/rest/v1/autotranslate.ts
  • app/definitions/rest/v1/channels.ts
  • app/definitions/rest/v1/chat.ts
  • app/definitions/rest/v1/commands.ts
  • app/definitions/rest/v1/customUserStatus.ts
  • app/definitions/rest/v1/e2e.ts
  • app/definitions/rest/v1/moderation.ts
  • app/definitions/rest/v1/settings.ts
  • app/definitions/rest/v1/teams.ts
  • app/definitions/rest/v1/videoConference.ts
  • app/lib/methods/getSlashCommands.ts
  • app/lib/services/restApi.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/definitions/rest/v1/chat.ts
🧰 Additional context used
🧬 Code graph analysis (6)
app/definitions/rest/v1/customUserStatus.ts (1)
app/definitions/rest/v1/index.ts (1)
  • Endpoints (25-47)
app/lib/methods/getSlashCommands.ts (1)
app/definitions/ISlashCommand.ts (1)
  • ISlashCommandResult (12-14)
app/definitions/rest/v1/commands.ts (1)
app/definitions/rest/v1/index.ts (1)
  • Endpoints (25-47)
app/definitions/rest/v1/autotranslate.ts (1)
app/definitions/rest/v1/index.ts (1)
  • Endpoints (25-47)
app/lib/services/restApi.ts (1)
app/lib/notifications/index.ts (1)
  • getDeviceToken (83-83)
app/definitions/rest/v1/settings.ts (1)
app/definitions/ISetting.ts (2)
  • ISettingColor (102-106)
  • ISetting (20-20)
🔇 Additional comments (17)
app/lib/methods/getSlashCommands.ts (3)

27-28: Reasonable type assertion for improved internal type safety.

The typed alias improves type safety within the function. Given that the null/length check on line 22 guards against undefined/empty cases, this is a safe approach.

However, the reliance on @ts-ignore at lines 14-15 and 20-21 suggests the SDK endpoint typings don't yet align with the actual API response shape. As this PR aims to use @rocket.chat/rest-typings as the single source of truth, consider creating a follow-up task to properly type the commands.list endpoint response so these @ts-ignore comments can be removed.


30-34: LGTM!

Consistent use of the typed commandsTyped variable in filter operations. The explicit type annotations on callback parameters (e.g., i1: ISlashCommandResult) are now technically redundant since TypeScript can infer them from the array type, but they don't hurt readability.


54-54: LGTM!

Correctly uses commandsTyped for the update lookup, ensuring consistent typing throughout the function.

app/definitions/rest/v1/autotranslate.ts (1)

1-15: Type transformation syntax is correct, but endpoint extraction requires verification.

The type transformation uses idiomatic TypeScript patterns—conditional mapped types and template literal string manipulation are syntactically sound. The RemoveV1Prefix utility correctly strips the /v1/ prefix from keys, and the overall pipeline structure is well-designed.

However, the success of this approach depends on whether the Endpoints type from @rocket.chat/rest-typings actually contains keys matching the /v1/autotranslate.${string} pattern. Verify that the rest-typings package exports autotranslate endpoints with this naming convention to ensure the extraction filter produces the expected keys.

app/definitions/rest/v1/videoConference.ts (1)

1-7: Clean utility type pattern for adapting upstream types.

The RemoveV1Prefix conditional type and the key remapping in AdaptVideoConferenceEndpoints are well-designed. This approach cleanly strips the /v1/ prefix from the canonical rest-typings package while preserving type safety.

app/lib/services/restApi.ts (6)

260-260: Acceptable migration workaround, but track for cleanup.

The as any cast here is a reasonable interim solution while integrating rest-typings. Consider adding a TODO comment or tracking issue to revisit these casts once the endpoint definitions are fully aligned.


473-478: LGTM with caveat.

The endpoint path cast is a necessary workaround. The explicit return type annotation maintains type safety for callers despite the internal as any.


599-601: Verify ignore parameter type for chat.ignoreUser endpoint.

The change to ignore.toString() suggests the rest-typings definition expects a string. Confirm this matches the Rocket.Chat server API expectation—some REST APIs accept boolean query params directly.


997-1002: LGTM!

The explicit type annotation 'apn' | 'gcm' improves clarity and ensures type safety for the push token type.


428-429: [Your rewritten review comment text here]
[Exactly ONE classification tag]


818-826: Breaking change: triggerId is now required.

All callers of runSlashCommand in the codebase already provide this parameter—for example, MessageComposer.tsx generates it via generateTriggerId(appId) before calling the function. No changes needed.

app/definitions/rest/v1/moderation.ts (1)

1-9: LGTM!

The type transformation correctly adapts RestTypingsModerationEndpoints by stripping the /v1/ prefix from endpoint keys. The implementation aligns with the broader migration pattern in this PR.

app/definitions/rest/v1/commands.ts (1)

1-15: LGTM - extraction approach is appropriate.

Since @rocket.chat/rest-typings doesn't export CommandsEndpoints directly, extracting them from the main Endpoints type using the key filter pattern is the correct approach. The transformation logic is sound.

app/definitions/rest/v1/customUserStatus.ts (1)

1-15: LGTM - type logic is correct.

The extraction and adaptation pattern correctly filters custom-user-status.* endpoints and strips the /v1/ prefix. Follows the same approach as commands.ts for endpoints not directly exported by @rocket.chat/rest-typings.

app/definitions/rest/v1/e2e.ts (1)

9-16: LGTM!

The adapter pattern correctly transforms the imported RestTypingsE2eEndpoints by stripping the /v1/ prefix, and the intersection type properly extends it with local endpoints that aren't yet in the package. The implementation aligns well with the PR objective of using @rocket.chat/rest-typings as the source of truth.

app/definitions/rest/v1/settings.ts (2)

1-10: Helper types and imports align with refactoring goal.

The RemoveV1Prefix and AdaptSettingsEndpoints utility types correctly strip the /v1/ prefix from upstream endpoint keys, enabling seamless integration with the existing codebase's endpoint naming convention. The special case handling for /v1/settings/:_id on line 9 is a clean approach.


18-34: Type guards correctly discriminate settings update variants.

The property-based checks ('execute' in props, 'editor' in props && 'value' in props, 'value' in props) properly narrow the union type at runtime. The order of checks matters when used in conditionals—ensure callers check isSettingsUpdatePropsActions and isSettingsUpdatePropsColor before isSettingsUpdatePropDefault since the latter's check is more general.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Fix unsafe type assertions by replacing 'as any' with safer 'as unknown as' casts
- Fix getSingleMessage to properly map _id to id field for IMessage interface
- Fix getUserPreferences to remove unsupported userId parameter
- Fix DiscussionsView to use proper type interface instead of 'as any'
- Fix ReadReceiptView to use safer type assertion with documentation
- Fix UserNotificationPreferencesView to use safer type assertion
- Fix isOauthCustomConfiguration type guard to perform actual validation
- Fix indentation issues in channels.ts, customUserStatus.ts, and teams.ts
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@app/lib/services/restApi.ts`:
- Around line 1084-1087: The function logoutOtherLocations assumes
reduxStore.getState().login.user.id exists; add a guard in logoutOtherLocations
to read const { id } = reduxStore.getState().login.user and if id is falsy
either throw a clear Error or return a rejected Promise (or no-op) before
calling sdk.post('users.removeOtherTokens'), and pass a correctly typed payload
(e.g., { userId: id }) only when id is present to avoid sending undefined to
users.removeOtherTokens.
♻️ Duplicate comments (2)
app/definitions/rest/v1/teams.ts (1)

5-9: Indentation issue on closing brace appears unresolved.

The past review flagged inconsistent indentation on line 7 (extra tab before };). This line was not modified in the current revision, so the fix may not have been applied.

🔧 Fix
 type AdaptTeamsEndpoints<T> = {
 	[K in keyof T as RemoveV1Prefix<K & string>]: T[K];
-	};
+};
app/definitions/rest/v1/customUserStatus.ts (1)

9-13: Type transformation logic is correct.

The RemoveV1Prefix conditional type and AdaptCustomUserStatusEndpoints mapped type correctly strip the /v1/ prefix from endpoint keys. The K & string intersection properly narrows the key type for template literal compatibility.

Note: An indentation issue on the closing brace was flagged in a previous review. Please ensure it has been addressed.

🧹 Nitpick comments (6)
app/lib/methods/getSingleMessage.ts (1)

4-5: Consider simplifying the Promise wrapper (optional).

The new Promise(async ...) pattern is redundant since async functions already return Promises. A simpler approach:

♻️ Suggested simplification
-const getSingleMessage = (messageId: string): Promise<IMessage> =>
-	new Promise(async (resolve, reject) => {
-		try {
-			const result = await getSingleMessageService(messageId);
-			if (result.success && result.message) {
-				const { message } = result;
-				// Map _id to id to match IMessage interface structure
-				// The API returns messages with _id, but IMessage requires id field
-				return resolve({
-					...message,
-					id: message._id
-				} as unknown as IMessage);
-			}
-			return reject();
-		} catch (e) {
-			return reject(e);
-		}
-	});
+const getSingleMessage = async (messageId: string): Promise<IMessage> => {
+	const result = await getSingleMessageService(messageId);
+	if (result.success && result.message) {
+		const { message } = result;
+		// Map _id to id to match IMessage interface structure
+		// The API returns messages with _id, but IMessage requires id field
+		return {
+			...message,
+			id: message._id
+		} as unknown as IMessage;
+	}
+	throw new Error('Failed to retrieve message');
+};
app/definitions/rest/v1/settings.ts (1)

36-65: Consider tightening unknown field types incrementally.

The extensive use of unknown for many fields is safer than any, but if the actual shapes of these OAuth configuration fields are known from LoginServiceConfiguration or backend documentation, consider typing them more precisely in a follow-up. This isn't blocking, but would improve type safety for consumers of this configuration.

app/lib/services/restApi.ts (4)

333-346: Consider preserving return type safety.

The Promise<any> return type discards type information. If the two endpoints return different response shapes, consider using a union type or generic to preserve type safety for callers.

-): Promise<any> => {
+): Promise<{ success: boolean }> => {

489-491: Consider separating query parameters from path.

Embedding query parameters in the path string is unconventional. If the SDK supports it, consider passing enabledDepartmentsOnly as a params object for clarity and type safety:

-	sdk.get(`livechat/agents/${uid}/departments?enabledDepartmentsOnly=true` as any);
+	sdk.get(`livechat/agents/${uid}/departments` as any, { enabledDepartmentsOnly: true });

647-652: Type alignment opportunity.

The as any casts for both data and customFields suggest the local IProfileParams definition may differ from @rocket.chat/rest-typings. Consider aligning the local type with the package definition to eliminate these casts.


426-435: Consider tracking missing endpoint type definition in a consolidated issue.

The as any casts on line 430 indicate livechat/inquiries.returnAsInquiry lacks type definitions from @rocket.chat/rest-typings. This pattern is consistent with other newer endpoints in the file (lines 652, 968, 1096). While the file already contains TODO comments for missing definitions elsewhere, consolidating these into a single tracking issue for batch-updating rest-typings when the package is updated would be more maintainable than scattered inline TODOs.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 853bf4e and 4b46bc8.

📒 Files selected for processing (9)
  • app/definitions/rest/v1/channels.ts
  • app/definitions/rest/v1/customUserStatus.ts
  • app/definitions/rest/v1/settings.ts
  • app/definitions/rest/v1/teams.ts
  • app/lib/methods/getSingleMessage.ts
  • app/lib/services/restApi.ts
  • app/views/DiscussionsView/index.tsx
  • app/views/ReadReceiptView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/views/ReadReceiptView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
app/lib/methods/getSingleMessage.ts (1)
app/definitions/IMessage.ts (1)
  • IMessage (147-178)
app/definitions/rest/v1/settings.ts (1)
app/definitions/ISetting.ts (2)
  • ISettingColor (102-106)
  • ISetting (20-20)
app/definitions/rest/v1/customUserStatus.ts (1)
app/definitions/rest/v1/index.ts (1)
  • Endpoints (25-47)
🔇 Additional comments (21)
app/definitions/rest/v1/teams.ts (1)

1-4: LGTM!

The type-only import and RemoveV1Prefix utility type are correctly implemented. The conditional template literal type correctly strips the /v1/ prefix when present.

app/lib/methods/getSingleMessage.ts (1)

8-15: Explicit _idid mapping addresses the prior type mismatch concern.

The change correctly maps the API's _id field to the id field required by IMessage. The spread pattern preserves all other fields while adding the required mapping. The as unknown as IMessage assertion is acceptable given the external API type constraints during this migration.

app/definitions/rest/v1/customUserStatus.ts (2)

1-7: LGTM! Type extraction logic is well-structured.

The use of template literal types to filter endpoints matching /v1/custom-user-status.${string} is an idiomatic approach for extracting a subset of the upstream Endpoints type.


15-15: Export correctly derives the type from upstream package.

This approach ensures CustomUserStatusEndpoints stays in sync with @rocket.chat/rest-typings while adapting the key format for local usage. This aligns well with the PR objective of using the package as the single source of truth.

app/definitions/rest/v1/channels.ts (1)

1-9: Clean implementation of the type adaptation pattern.

The use of RemoveV1Prefix and AdaptChannelsEndpoints helper types to derive endpoints from @rocket.chat/rest-typings is consistent with the PR's goal and follows the same pattern used in other endpoint files.

app/definitions/rest/v1/settings.ts (3)

18-34: AI summary is inconsistent with actual code.

The AI summary states that runtime type guards (isSettingsUpdatePropsActions, isSettingsUpdatePropsColor, isSettingsUpdatePropDefault) were removed, but they are clearly present and correctly implemented in the code.


67-72: Type guard now provides meaningful validation.

This implementation properly checks for the presence and types of required fields (_id, loginStyle) and validates the loginStyle value. This addresses the previous concern about the type guard accepting any truthy value.


74-87: Override documentation added as requested.

The comments on lines 81-82 now clearly explain why settings/:_id is overridden from upstream types. This addresses the previous review concern about documenting the intentional override.

Note that the intersection type semantics will merge both the upstream and local type definitions for settings/:_id. As long as the local types (ISetting, SettingsUpdateProps) remain compatible with the actual API responses, this approach maintains type safety while preserving codebase compatibility.

app/lib/services/restApi.ts (13)

260-260: Acceptable cast for conditional payload structure.

The as any cast here accommodates the varying params shape based on server version and channel type. This is a reasonable workaround during the rest-typings migration.


271-277: LGTM!

Explicitly converting null to undefined via ?? ensures the payload conforms to expected typing where joinCode should be string | undefined rather than string | null.


359-362: LGTM - past review concern addressed.

The userId parameter has been correctly removed, aligning with the Rocket.Chat API documentation where users.getPreferences returns preferences for the authenticated user based on headers only.


474-479: Acceptable cast for newer endpoint.

The livechat/config/routing endpoint (RC 7.11.0+) may not be in @rocket.chat/rest-typings yet. The cast is appropriate for forward compatibility.


600-602: LGTM!

Converting the boolean ignore to a string aligns with REST API query parameter conventions where boolean values are typically passed as 'true'/'false' strings.


658-660: Acceptable migration cast.

The as any cast for notifications parameter follows the same pattern. Consider aligning IRoomNotifications with the rest-typings definition in a follow-up.


697-704: LGTM!

The as any cast for the sort parameter accommodates the MongoDB-style sort format (-1 for descending) which may not match the strict typing in rest-typings.


798-810: LGTM!

The params object is well-typed locally with explicit optional text handling. The as any cast bridges the gap with rest-typings definitions.


819-827: LGTM!

The triggerId parameter is now explicitly typed as a required string, improving type safety for slash command execution.


971-992: LGTM!

The editMessage function correctly handles both encrypted (content) and non-encrypted (text) message updates. The as any casts accommodate the different payload shapes required by chat.update.


994-1012: LGTM!

Narrowing type to 'apn' | 'gcm' union improves type safety by restricting to the only valid push notification types for iOS and Android respectively.


1096-1096: Acceptable cast for missing endpoint definition.

The rooms.invite endpoint may not be defined in @rocket.chat/rest-typings. The action parameter is well-typed as a union. Consider tracking this for future type alignment.


966-969: Document the minimum server version for this endpoint.

The RC ? comment indicates uncertainty about when e2e.resetRoomKey was introduced. Unlike other e2e endpoints in this file that document specific versions (RC 0.70.0, 2.2.0, 5.5), this one lacks version information. Investigate the Rocket.Chat server documentation or changelog to identify and document the minimum supported version.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

…necessary comments

- Add guard to check if user id exists before calling users.removeOtherTokens
- Return rejected promise with error message if user is not logged in
- Improves error handling and code cleanliness
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore: Add @rocket.chat/rest-typings

2 participants